package vip.liux.backend.adapter.web;

import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import vip.liux.application.dots.PagedResultDto;
import vip.liux.backend.application.service.pay.*;
import vip.liux.backend.application.service.pay.dto.notify.PayNotifyTaskDetailDto;
import vip.liux.backend.application.service.pay.dto.notify.PayNotifyTaskDto;
import vip.liux.backend.application.service.pay.dto.notify.PayNotifyTaskQueryDto;
import vip.liux.contracts.infrastructure.pay.PayClient;
import vip.liux.contracts.infrastructure.pay.dto.order.ClientPayOrderDto;
import vip.liux.contracts.infrastructure.pay.dto.refund.ClientPayRefundDto;
import vip.liux.contracts.infrastructure.pay.dto.transfer.ClientPayTransferDto;

import java.util.Map;

import static vip.liux.contracts.shared.enums.ErrorCode.CHANNEL_NOT_FOUND;
import static vip.liux.contracts.shared.util.ServiceExceptionUtil.exception;

@RestController
@RequestMapping("/api/pay/notify")
@Slf4j
public class PayNotifyController {

    @Resource
    private PayChannelService channelService;
    @Resource
    private PayOrderService orderService;
    @Resource
    private PayRefundService refundService;
    @Resource
    private PayTransferService transferService;
    @Resource
    private PayNotifyService notifyService;

    @PostMapping(value = "/order/{channelId}")
    public String notifyOrder(
            @PathVariable("channelId") Long channelId,
            @RequestParam(required = false) Map<String, String> params,
            @RequestBody(required = false) String body,
            @RequestHeader Map<String, String> headers) {
        log.info("[notifyOrder][channelId({}) 回调数据({}/{})]", channelId, params, body);
        // 1. 校验支付渠道是否存在
        PayClient<?> payClient = channelService.getPayClient(channelId);
        if (payClient == null) {
            log.error("[notifyOrder][渠道编号({}) 找不到对应的支付客户端]", channelId);
            throw exception(CHANNEL_NOT_FOUND);
        }

        // 2. 解析通知数据
        ClientPayOrderDto notify = payClient.parseOrderNotify(params, body, headers);
        orderService.notifyOrder(channelId, notify);
        return "success";
    }

    @PostMapping(value = "/refund/{channelId}")
    public String notifyRefund(
            @PathVariable("channelId") Long channelId,
            @RequestParam(required = false) Map<String, String> params,
            @RequestBody(required = false) String body,
            @RequestHeader Map<String, String> headers) {
        log.info("[notifyRefund][channelId({}) 回调数据({}/{})]", channelId, params, body);
        // 1. 校验支付渠道是否存在
        PayClient<?> payClient = channelService.getPayClient(channelId);
        if (payClient == null) {
            log.error("[notifyRefund][渠道编号({}) 找不到对应的支付客户端]", channelId);
            throw exception(CHANNEL_NOT_FOUND);
        }

        // 2. 解析通知数据
        ClientPayRefundDto notify = payClient.parseRefundNotify(params, body, headers);
        refundService.notifyRefund(channelId, notify);
        return "success";
    }

    @PostMapping(value = "/transfer/{channelId}")
    public String notifyTransfer(
            @PathVariable("channelId") Long channelId,
            @RequestParam(required = false) Map<String, String> params,
            @RequestBody(required = false) String body,
            @RequestHeader Map<String, String> headers) {
        log.info("[notifyTransfer][channelId({}) 回调数据({}/{})]", channelId, params, body);
        // 1. 校验支付渠道是否存在
        PayClient<?> payClient = channelService.getPayClient(channelId);
        if (payClient == null) {
            log.error("[notifyTransfer][渠道编号({}) 找不到对应的支付客户端]", channelId);
            throw exception(CHANNEL_NOT_FOUND);
        }

        // 2. 解析通知数据
        ClientPayTransferDto notify = payClient.parseTransferNotify(params, body, headers);
        transferService.notifyTransfer(channelId, notify);
        return "success";
    }

    @GetMapping("/detail")
    public PayNotifyTaskDetailDto getNotifyTaskDetail(@RequestParam("id") Long id) {
        return notifyService.getNotifyTaskDetail(id);
    }

    @GetMapping("/page")
    public PagedResultDto<PayNotifyTaskDto> getNotifyTaskPage(PayNotifyTaskQueryDto input) {
        return notifyService.getNotifyTaskPage(input);
    }
}
